home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / weyl / weyl_lsp.lha / lisp-numbers.lisp < prev    next >
Text File  |  1991-10-29  |  13KB  |  493 lines

  1. ;;; -*- Mode:Lisp; Package:Weyli; Base:10; Lowercase:T; Syntax:Common-Lisp -*-
  2. ;;; ===========================================================================
  3. ;;;                  Lisp Numbers
  4. ;;; ===========================================================================
  5. ;;; (c) Copyright 1989, 1991 Cornell University
  6.  
  7. ;;; $Id: lisp-numbers.lisp,v 2.21 1991/10/30 00:00:39 rz Exp $
  8.  
  9.  
  10. (in-package "WEYLI")
  11.  
  12. (define-domain-element-classes floating-point-numbers float)
  13.  
  14. (defmethod print-object ((d floating-point-numbers) stream)
  15.   #-Genera
  16.   (format stream "R")
  17.   #+Genera
  18.   (format stream "~'bR~"))
  19.  
  20. (defvar *floating-point-numbers* (make-instance 'floating-point-numbers))
  21.  
  22. ;; This isn't quite right yet, since I don't have the special type of
  23. ;; floating point number yet.
  24. ;; The class: REAL-NUMBERS is defined in bigfloat.lisp
  25. (define-domain-creator real-numbers (&optional (precision 16))
  26.   (if (= precision 16)
  27.       *floating-point-numbers*
  28.       (make-instance 'real-numbers :precision precision)))
  29.  
  30. ;; This is slightly inefficient, but who cares...  I want to localize
  31. ;; the knowledge of how to create domains in the MAKE-...* functions.
  32. (defun get-real-numbers (&optional (precision 16))
  33.   (if (= precision 16)
  34.       (add-domain (lambda (d)
  35.             (eql d *floating-point-numbers*))
  36.     (make-real-numbers* precision))
  37.       (add-domain (lambda (d)
  38.         (and (eql (class-name (class-of d)) 'real-numbers)
  39.              (eql (fp-precision d) precision)))
  40.     (make-real-numbers* precision))))
  41.  
  42. ;; The Lisp number domain is a special field whose elements are
  43. ;; represented as Lisp numbers.  This class is unique.
  44.  
  45. (define-domain-element-classes lisp-numbers
  46.     integer rational)
  47.  
  48. (defmethod print-object ((d lisp-numbers) stream)
  49.   #+Genera
  50.   (format stream "~'bQlisp~")
  51.   #-Genera
  52.   (princ "Qlisp"  stream))
  53.  
  54. #+IGNORE  ; Defined in domain-support...
  55. (defvar *lisp-numbers* (make-instance 'lisp-numbers))
  56.  
  57. (defun get-lisp-numbers ()
  58.   (or *lisp-numbers*
  59.       (error "You need to RESET-DOMAINS!")))
  60.  
  61. (defun make-lisp-numbers ()
  62.   (get-lisp-numbers))
  63.  
  64. (defmethod domain-of ((element float))
  65.   *floating-point-numbers*)
  66.  
  67. (defmethod domain-of ((element (or integer ratio lisp:complex)))
  68.   *lisp-numbers*)
  69.  
  70. (defmethod number? ((element t))
  71.   nil)
  72.  
  73. (defmethod number? ((element number))
  74.   t)
  75.  
  76. ;; Special printer for complex numbers to that they are more readable.
  77. (defmethod print-object ((c lisp:complex) stream)
  78.   (cond ((lisp:zerop (imagpart c))
  79.      (princ (realpart c) stream ))
  80.     ((lisp:zerop (realpart c))
  81.      (format stream "(~S i)" (imagpart c)))
  82.     (t (format stream "(~S + ~S i)" (realpart c) (imagpart c)))))
  83.  
  84. ;;For documentation purposes  (provided by Lisp)
  85. #+ignore
  86. (defmethod print-object ((n number) stream)
  87.   (princ n stream))
  88.  
  89. (defmethod numerator ((r integer))
  90.   r)
  91.  
  92. (defmethod denominator ((r integer))
  93.   1)
  94.  
  95. (defmethod numerator ((r ratio))
  96.   (lisp::numerator r))
  97.  
  98. (defmethod denominator ((r ratio))
  99.   (lisp::denominator r))
  100.  
  101. (defmethod < ((x number) (y number))
  102.   (lisp:< x y))
  103.  
  104. (defmethod <= ((x number) (y number))
  105.   (lisp:<= x y))
  106.  
  107. (defmethod = ((x number) (y number))
  108.   (lisp:= x y))
  109.  
  110. (defmethod >= ((x number) (y number))
  111.   (lisp:>= x y))
  112.  
  113. (defmethod > ((x number) (y number))
  114.   (lisp:> x y))
  115.  
  116. (defmethod max-pair ((x number) (y number))
  117.   (if (lisp:> x y) x y))
  118.  
  119. (defmethod min-pair ((x number) (y number))
  120.   (if (lisp:> x y) y x))
  121.  
  122. (defmethod 0? ((x number))
  123.   (lisp:zerop x))
  124.  
  125. (defmethod 1? ((x number))  
  126.   (= x 1))
  127.  
  128. (defmethod zero ((r lisp-numbers))
  129.   0)
  130.  
  131. (defmethod one ((r lisp-numbers))
  132.   1)
  133.  
  134. (defmethod minus ((x number))
  135.   (lisp:- x))
  136.  
  137. (defmethod minus? ((x number))
  138.   (lisp:minusp x))
  139.  
  140. (defmethod minus? ((x lisp:complex))
  141.   nil)
  142.  
  143. (defmethod plus? ((x number))
  144.   (lisp:plusp x))
  145.  
  146. (defmethod plus? ((x lisp:complex))
  147.   (not (lisp:zerop x)))
  148.  
  149. (defmethod abs ((x number))
  150.   (lisp:abs x))
  151.  
  152. ;; The explicit mention of integer is needed to overide the coercions
  153. ;; in coercions.lisp
  154.  
  155. (defmethod plus ((x (or integer number)) (y (or integer number)))
  156.   (lisp:+ x y))
  157.  
  158. (defmethod difference ((x (or integer number)) (y (or integer number)))
  159.   (lisp:- x y))
  160.  
  161. (defmethod times ((x (or integer number)) (y (or integer number)))
  162.   (lisp:* x y))
  163.  
  164. (defmethod recip ((x number))
  165.   (lisp:/ x))
  166.  
  167. (defmethod expt ((n number) (e number))
  168.   (lisp:expt n e))
  169.  
  170. (defmethod quotient ((a (or integer number)) (b (or integer number)))
  171.   (lisp:/ a b))
  172.  
  173. (defmethod floor ((a number) &optional b)
  174.   (if b
  175.       (lisp:floor a b)
  176.       (lisp:floor a)))
  177.  
  178. (defmethod ceiling ((a number) &optional b)
  179.   (if b
  180.       (lisp:ceiling a b)
  181.       (lisp:ceiling a)))
  182.  
  183. (defmethod truncate ((a number) &optional b)
  184.   (if b
  185.       (lisp:truncate a b)
  186.       (lisp:truncate a)))
  187.  
  188. (defmethod round ((a number) &optional b)
  189.   (if b
  190.       (lisp:round a b)
  191.       (lisp:round  a)))
  192.  
  193. (defmethod remainder ((a number) (b number))
  194.   (lisp:rem a b))
  195.  
  196. (defmethod gcd ((a integer) (b integer))
  197.   (lisp:gcd a b))
  198.  
  199. ;; Do we really need this???
  200. (defmethod gcd ((a float) (b float))
  201.   a)
  202.  
  203. (defmethod lcm ((a integer) (b integer))
  204.   (lisp:* (lisp:/ a (lisp:gcd a b)) b))
  205.  
  206. (defun faster-isqrt (n)
  207.   (let (n-len-quarter n-half n-half-isqrt init-value q r iterated-value)
  208.     "argument n must be a non-negative integer"
  209.     (cond
  210.       ((> n 24)
  211.        ;; theoretically (> n 7) ,i.e., n-len-quarter > 0
  212.        (setq n-len-quarter (ash (integer-length n) -2))
  213.        (setq n-half (ash n (- (ash n-len-quarter 1))))
  214.        (setq n-half-isqrt (faster-isqrt n-half))
  215.        (setq init-value (ash (1+ n-half-isqrt) n-len-quarter))
  216.        (multiple-value-setq (q r) (floor n init-value))
  217.        (setq iterated-value (ash (+ init-value q) -1))
  218.        (if (eq (logbitp 0 q) (logbitp 0 init-value)) ; same sign
  219.        ;; average is exact and we need to test the result
  220.        (let ((m (- iterated-value init-value)))
  221.          (if (> (* m m) r)
  222.          (- iterated-value 1)
  223.          iterated-value))
  224.        ;; average was not exact, we take value
  225.        iterated-value))
  226.       ((> n 15) 4)
  227.       ((> n  8) 3)
  228.       ((> n  3) 2)
  229.       ((> n  0) 1)
  230.       ((> n -1) 0)
  231.       (t nil))))
  232.  
  233. (defvar *big-primes* ()
  234.   "List of large primes by decending size")
  235.  
  236. ;; Return the next prime less than its argument, and that fits into a
  237. ;; word.  
  238. (defun newprime (p)
  239.   (do ((pl *big-primes* (cdr pl)))
  240.       ((null pl) (setq p (find-smaller-prime p))
  241.        (setq *big-primes* (nconc *big-primes* (list p)))
  242.        p)
  243.     (if (lisp:< (car pl) p) (return (car pl)))))
  244.  
  245. ;; Rabin's probabilistic primality algorithm isn't used here because it
  246. ;; isn't much faster than the simple one for numbers about the size of a
  247. ;; word.
  248. (defun find-smaller-prime (p)
  249.   "Finds biggest prime less than fixnum p"
  250.   (if (evenp p) (setq p (1- p)))
  251.   (loop for pp = (lisp:- p 2) then (lisp:- pp 2) until (lisp:< pp 0)
  252.     when (prime? pp)
  253.       do (return pp)))
  254.  
  255. (defun repeated-squaring (mult one)
  256.   (lambda (base exp)
  257.     (if (lisp:zerop exp) one
  258.     (let ((prod one))
  259.       (loop
  260.         (if (oddp exp)
  261.         (setq prod (%funcall mult prod base)))
  262.         (setq exp (truncate exp 2))
  263.         (if (lisp:zerop exp)
  264.         (return prod))
  265.         (setq base (%funcall mult base base)))))))
  266.  
  267. (defmethod power-of? ((m integer) &optional n)
  268.   (cond ((typep n 'integer)
  269.      (loop for test = n then (* test n)
  270.            for i upfrom 1
  271.            when (= test m)
  272.          do (return (values n i))
  273.            when (> test m)
  274.          do (return nil)))
  275.     (t (error "Haven't implemented the rest of the cases"))))
  276.  
  277. ;; These two really should be in GFP, but because of LUCID braindamage,
  278. ;; they have to be here to avoid warnings.
  279.  
  280. (defun reduce-modulo-integer (value modulus)
  281.   (unless (lisp:zerop modulus)
  282.     (setq value (lisp:rem value modulus)))
  283.   (if (lisp:< value 0) (lisp:+ value modulus)
  284.       value))
  285.  
  286. (defun expt-modulo-integer (base expt modulus)  
  287.   (%funcall (repeated-squaring
  288.           (lambda (a b) (reduce-modulo-integer (lisp:* a b) modulus))
  289.           1)
  290.         base expt)) 
  291.  
  292. (defmethod prime? ((p integer))
  293.   (and (or (lisp:< p 14.)
  294.        (and (lisp:= 1 (expt-modulo-integer 13. (1- p) p))
  295.         (lisp:= 1 (expt-modulo-integer 3 (1- p) p))))
  296.        (null (cdr (setq p (factor p))))
  297.        (lisp:= 1 (cdar p))))
  298.  
  299. (defun all-divisors (n)
  300.   (let ((factors (factor n)))
  301.     (loop with divisors = (list 1)
  302.       for (prime . times) in factors
  303.       do (loop for i from 1 to times
  304.            appending (loop for divisor in divisors
  305.                    collect (* divisor (lisp:expt prime i)))
  306.              into temp
  307.            finally (setq divisors (append temp divisors)))
  308.          finally (return (sort divisors #'lisp:<)))))
  309.  
  310. (defvar *factor-method* 'simple-integer-factor)
  311.  
  312. (defmacro count-multiple-integer-factors (N divisor)
  313.   `(loop with i = 0
  314.      do (multiple-value-bind (quo rem) (lisp:truncate ,N ,divisor)
  315.           (when (not (lisp:zerop rem))
  316.         (if (not (lisp:zerop i))
  317.             (push (cons ,divisor i) ans))
  318.         (return t))
  319.           (setq ,N quo)
  320.           (incf i))))
  321.  
  322. (defmethod factor ((N integer))
  323.   (let ((*factor-method* *factor-method*)
  324.     ans factors)
  325.     (when (lisp:minusp N)
  326.       (push (cons -1 1) ans)
  327.       (setq N (lisp:- N)))
  328.     (count-multiple-integer-factors N 2)
  329.     (count-multiple-integer-factors N 3)
  330.     (count-multiple-integer-factors N 5)
  331.     (unless (lisp::= N 1)
  332.       (loop
  333.     (multiple-value-setq (N factors) (%funcall *factor-method* N))
  334.     (setq ans (append factors ans))
  335.     (if (lisp::= N 1) (return t))))
  336.     (uniformize-factor-list ans)))
  337.  
  338. (defun uniformize-factor-list (ans)
  339.   (loop for pairs on (sort ans (lambda (a b) (< (first a) (first b))))
  340.     when (or (null (rest pairs))
  341.          (not (lisp::= (first (first pairs))
  342.              (first (second pairs)))))
  343.       collect (first pairs)
  344.     else do (incf (rest (second pairs)))))
  345.  
  346. ;; In general each factorization method should return just one factor.
  347.  
  348. (defvar *skip-chain-for-3-and-5* (circular-list 4 2 4 2 4 6 2 6))
  349.  
  350. (defun simple-integer-factor (N)
  351.   (let ((increments *skip-chain-for-3-and-5*)
  352.     (divisor 7)
  353.     ans)
  354.     (flet ((simple-integer-factor-internal (N)
  355.          (let ((limit (lisp:isqrt N)))
  356.            (loop 
  357.          (cond ((lisp:= N 1)
  358.             (return (values N ans)))
  359.                ((lisp:> divisor limit)
  360.             (return (values 1 (list (cons N 1)))))
  361.                (t (count-multiple-integer-factors N divisor)))
  362.          (setq divisor (lisp:+ divisor (pop increments)))))))      
  363.       (setq *factor-method* #'simple-integer-factor-internal)
  364.       (simple-integer-factor-internal N))))
  365.  
  366. (defun fermat-integer-factor (N)
  367.   (loop for x = (1+ (lisp:isqrt N)) then (+ x 1)
  368.     for w = (lisp:- (lisp:* x x) N)
  369.     for y = (lisp:isqrt w)
  370.     do (when (lisp:zerop (lisp:- w (lisp:* y y)))
  371.          (let ((u (lisp:+ x y))
  372.            (v (lisp:- x y)))
  373.            (return (if (1? v)
  374.                (values 1 (list (cons u 1)))
  375.                (values u (factor v))))))))
  376.     
  377. #| Knuth's addition-subtraction version of Fermat's algorithm |
  378.  
  379. (defun fermat-integer-factor (N)
  380.   (let* ((isqrt-N (lisp:isqrt N))
  381.      (x (1+ (* 2 isqrt-N)))
  382.      (y 1)
  383.      (r (- (* isqrt-N isqrt-N) N)))
  384.     (loop
  385.       (cond ((= r 0)
  386.          (return 
  387.            (let ((f (/ (+ x y -2) 2))
  388.              (g (/ (- x y) 2)))
  389.          (if (= g 1)
  390.              (values 1 (list (cons f 1)))
  391.              (values 1 (append (factor f) (factor g)))))))
  392.         ((< r 0)
  393.          (incf r x)
  394.          (incf x 2)))
  395.       (decf r y)
  396.       (incf y 2))))
  397.  
  398. (defun list-of-primes (N)
  399.   (cons 2
  400.     (loop for p upfrom 3 by 2 below N
  401.           when (prime? p) collect p)))
  402.  
  403. (defun make-integer-GCD-list (max-prime size-limit)
  404.   (let ((GCD-list ()))
  405.     (loop for p in (list-of-primes max-prime)
  406.       with prod = 1 and prime-list = ()
  407.       do (setq prod (* prod p))
  408.          (cond ((> prod size-limit)
  409.             (push (list (/ prod p) prime-list)
  410.               GCD-list)
  411.             (setq prod p)
  412.             (setq prime-list (list p)))
  413.            (t (push p prime-list))))
  414.     GCD-list))
  415.  
  416.         
  417. ||#
  418.  
  419. (defun totient (x)
  420.   (do ((factors (factor x) (rest factors))
  421.        (totient 1 (lisp:* totient
  422.               (lisp:- (lisp:expt (caar factors) (cdar factors))
  423.                   (lisp:expt (caar factors) (1- (cdar factors)))))))
  424.       ((null factors)
  425.        totient)))
  426.  
  427. (defmethod sqrt ((x number))
  428.   (lisp:sqrt  x))
  429.  
  430. (defmethod sin ((x number))
  431.   (lisp:sin x))
  432.  
  433. (defmethod cos ((x number))
  434.   (lisp:cos x))
  435.  
  436. (defmethod tan ((x number))
  437.   (lisp:tan x))
  438.  
  439. (defmethod asin ((x number))
  440.   (lisp:asin x))
  441.  
  442. (defmethod acos ((x number))
  443.   (lisp:acos x))
  444.  
  445. (defmethod atan ((x number) &optional y)
  446.   (cond ((null y)
  447.      (lisp:atan x))
  448.     ((numberp y)
  449.      (lisp:atan x y))
  450.     (t (atan (coerce x (domain-of y)) y))))
  451.  
  452. (defmethod sinh ((x number))
  453.   (lisp:sinh x))
  454.  
  455. (defmethod cosh ((x number))
  456.   (lisp:cosh x))
  457.  
  458. (defmethod tanh ((x number))
  459.   (tanh x))
  460.  
  461. (defmethod asinh ((x number))
  462.   (lisp:asinh x))
  463.  
  464. (defmethod acosh ((x number))
  465.   (lisp:acosh x))
  466.  
  467. (defmethod atanh ((x number))
  468.   (lisp:atanh x))
  469.  
  470. (defmethod exp ((x number))
  471.   (lisp:exp x))
  472.  
  473. (defmethod log2 ((x number) (base number))
  474.   (lisp:log x base))
  475.  
  476. (defmethod log ((x number))
  477.   (lisp:log x))
  478.  
  479. (defmethod conjugate  ((x number))
  480.   (lisp:conjugate x))
  481.  
  482. (defmethod realpart ((x number))
  483.   (lisp:realpart x))
  484.  
  485. (defmethod imagpart ((x number))
  486.   (lisp:imagpart x))
  487.  
  488. (defmethod phase ((x number))
  489.   (lisp:phase x))
  490.  
  491. (defmethod signum ((x number))
  492.   (lisp:signum x))
  493.